#ifndef MSGD_EVENT_H
#define MSGD_EVENT_H 1

struct msgd_event_s {
  void * data;
 
  msgd_event_t  *next;
  msgd_event_t  **prev;

  queue_t      queue;

  msgd_rbtree_node_t timer; 

  msgd_atomic_t *lock;

  unsigned write:1;
  unsigned accept:1;
  unsigned active:1;
  unsigned disable:1;
  unsigned timedout:1;
  unsigned timer_set:1;

  msgd_event_handler_pt handler; 
};

typedef struct {
    msgd_int_t  (*add)(msgd_event_t *ev, msgd_int_t event, msgd_int_t flags);
    msgd_int_t  (*del)(msgd_event_t *ev, msgd_int_t event, msgd_int_t flags);

    msgd_int_t  (*process_changes)(msgd_uint_t nowait);
    msgd_int_t  (*process_events)(msgd_int_t timer, msgd_int_t flags);

    msgd_int_t  (*init)();
    void        (*done)();
} msgd_event_actions_t;


extern msgd_event_actions_t   msgd_event_actions;
extern block_queue_t         msgd_posted_events_queue;

#define msgd_process_changes  msgd_event_actions.process_changes
#define msgd_process_events   msgd_event_actions.process_events
#define msgd_done_event       msgd_event_actions.done
#define msgd_init_event       msgd_event_actions.init


#define msgd_add_event        msgd_event_actions.add
#define msgd_del_event        msgd_event_actions.del


#define msgd_add_timer        msgd_event_add_timer
#define msgd_del_timer        msgd_event_del_timer


#define msgd_locked_post_event(ev , queue)				    \
								            \
   if( ev->prev == NULL) {					            \
      ev->next = (msgd_event_t*)*queue;					    \
      ev->prev = (msgd_event_t**)queue;					    \
      *queue = ev;							    \
									    \
      if(ev->next){							    \
        ev->next->prev = &ev->next;					    \
      }									    \
									    \
      DEBUG("post event :%p",ev);					    \
   }else{								    \
      DEBUG("update posted event :%p",ev);				    \
   }									    


#define msgd_delete_posted_event(ev)                                        \
									    \
    *(ev->prev) = ev->next;                                                 \
									    \
    if (ev->next) {                                                         \
        ev->next->prev = ev->prev;                                          \
    }                                                                       \
                                                                            \
    ev->prev = NULL;                                                        \
    DEBUG("delete posted event %p", ev);


#define msgd_event_ident(ev)  (((msgd_connection_t*)(ev->data))->fd) 

#define MAX_SOCKET_LEN  sizeof(struct sockaddr_un)
#define CONN_POLL_SIZE  1024*4

extern volatile msgd_uint_t msgd_current_msec;

#ifdef __cplusplus
extern "C" {
#endif

void msgd_event_accept(msgd_event_t *ev);

void msgd_empty_write_handler(msgd_event_t *wev);

msgd_int_t msgd_handle_read_event(msgd_event_t *rev);

void msgd_handle_posted_event(msgd_event_t **queue);

void msgd_time_update(void);

#ifdef __cplusplus
}
#endif

#endif //MSGD_EVENT_H
